<html>
<head><meta charset="utf-8"><title>Transmuting Locks on Std IO · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html">Transmuting Locks on Std IO</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="184867275"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184867275" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184867275">(Jan 05 2020 at 22:07)</a>:</h4>
<p>So I have an <code>ncurses</code> style situation. I want to have a struct that represents "the terminal", and it will have exclusive control over the input and output handling while it's around. Naturally, Rust puts us in a thread-safe position for this with the <code>StdinLock</code>, <code>StdoutLock</code>, and <code>StderrLock</code> setup. However, each of these locks holds a lifetime back to their handle. So you'd have a struct with three lifetimes to some outer scope the terminal is stuck in. It would be a lot easier if the terminal could just hold all of the stuff at once and then it can just move around without worry. Which brings us to questions about how we could package up the handles with the locks.</p>
<p>(For the purposes of everything I'm about to say, I'm aware that the internals of the standard library are not a stable part of the API. I'm willing to accept that some future version of the standard library might change a detail in here, I just want it to be sound with respect to current Rust.)</p>
<p>So my main thought was that we can just transmute the lock from lock&lt;'a&gt; into lock&lt;'static&gt;, wrap both the handle and the lock into ManuallyDrop, and then have the drop code for this bundle first drop the lock, then drop the handle. </p>
<p>The handles themselves are of the form <code>Arc&lt;Mutex&lt;BufReader&lt;Maybe&lt;StdinRaw&gt;&gt;&gt;&gt;</code>, and the lock is a <code>MutexGuard&lt;'a, BufReader&lt;Maybe&lt;StdinRaw&gt;&gt;&gt;</code>. The <code>Arc&lt;Mutex&lt;...&gt;&gt;</code> itself is kept, lazily initialized, <a href="https://doc.rust-lang.org/src/std/io/stdio.rs.html#242-259" target="_blank" title="https://doc.rust-lang.org/src/std/io/stdio.rs.html#242-259">in a static inside the stdin function</a>.</p>
<p>Given what I want to accomplish, does this sound like a sane sort of thing to do? Is there some better way to do it?</p>



<a name="184869608"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184869608" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184869608">(Jan 05 2020 at 23:10)</a>:</h4>
<p><code>rental</code>?</p>



<a name="184967365"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184967365" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184967365">(Jan 06 2020 at 23:17)</a>:</h4>
<p>That looks... way too complicated. Seems like a swiss army chainsaw for when you have actual references to things that are supposed to move.</p>



<a name="184982009"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982009" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982009">(Jan 07 2020 at 04:45)</a>:</h4>
<p><span class="user-mention" data-user-id="224471">@Lokathor</span> <em>shrug</em> In any case, the implementation of rental does the same thing you proposed to do, transmuting lifetimes.  It should be fine, honestly even in the face of future changes, unless we somehow give up on the idea that lifetimes are erased at runtime.</p>



<a name="184982183"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982183" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982183">(Jan 07 2020 at 04:50)</a>:</h4>
<p>But in terms of complexity... <code>rental</code> is designed for pretty much the exact use case you have.  A struct with two fields, where one is an owning pointer (like <code>Box</code>, or in your case <code>Arc</code>), and the other is a reference to the data behind that pointer.</p>



<a name="184982206"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982206" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982206">(Jan 07 2020 at 04:51)</a>:</h4>
<p>But it <em>is</em> ugly, because it's trying to shoehorn something into Rust's existing type system that it wasn't designed to do.</p>



<a name="184982256"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982256" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982256">(Jan 07 2020 at 04:52)</a>:</h4>
<p>On the other hand, it is safe.</p>



<a name="184982271"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982271" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982271">(Jan 07 2020 at 04:53)</a>:</h4>
<p>Your choice whether to go for the safe-but-ugly option or the unsafe-but-slightly-less-ugly one. :)</p>



<a name="184982319"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982319" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982319">(Jan 07 2020 at 04:54)</a>:</h4>
<p>The biggest thing in this case, to me at least, isn't so much safe vs unsafe. It's the ergonomics factors. You don't get any fields any more, you have all sorts of closures to try and use.</p>



<a name="184982325"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982325" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982325">(Jan 07 2020 at 04:54)</a>:</h4>
<p>So it's very very less ugly to be able to just use the fields directly in all the rest of the type's methods.</p>



<a name="184982452"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982452" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982452">(Jan 07 2020 at 04:58)</a>:</h4>
<p>mm, let me check something</p>



<a name="184982465"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982465" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982465">(Jan 07 2020 at 04:59)</a>:</h4>
<p><em>letting</em></p>



<a name="184982676"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982676" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982676">(Jan 07 2020 at 05:04)</a>:</h4>
<p>yeah, ok, there's no way around the closures :)</p>



<a name="184982679"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982679" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982679">(Jan 07 2020 at 05:05)</a>:</h4>
<p>suit yourself then</p>



<a name="184982697"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982697" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982697">(Jan 07 2020 at 05:05)</a>:</h4>
<p>For the general case of references literally pointing to other fields, you'd need that</p>



<a name="184982741"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982741" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982741">(Jan 07 2020 at 05:06)</a>:</h4>
<p>But since it's an Arc Mutex and an Arc MutexGuard (which points to the inner mutex on the heap), neither field in my case actually points to the other</p>



<a name="184982745"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982745" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982745">(Jan 07 2020 at 05:06)</a>:</h4>
<p>nah, if you have references literally pointing to other fields, you can't move, period</p>



<a name="184982758"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982758" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982758">(Jan 07 2020 at 05:06)</a>:</h4>
<p>whereas <code>rental</code> is for cases where the outer struct can move, because the references points to something behind a heap allocation</p>



<a name="184982770"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982770" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982770">(Jan 07 2020 at 05:07)</a>:</h4>
<p>like I said, pretty much your exact use case</p>



<a name="184982775"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982775" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982775">(Jan 07 2020 at 05:07)</a>:</h4>
<p>but using unsafe code is fine too :)</p>



<a name="184982777"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982777" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982777">(Jan 07 2020 at 05:07)</a>:</h4>
<p>oh really? yikes I figured it was like... you'd say you'd want &amp;i32 and then it'd store an i32 and then during the closure it'd pass that i32 as well as the reference to wherever it currently was</p>



<a name="184982780"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982780" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982780">(Jan 07 2020 at 05:07)</a>:</h4>
<p>oh, and regarding whether it's sound: it's significant that Stacked Borrows does not care about lifetimes (although it does care about references versus raw pointers)</p>



<a name="184982839"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982839" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982839">(Jan 07 2020 at 05:08)</a>:</h4>
<p>although...</p>



<a name="184982853"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982853" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982853">(Jan 07 2020 at 05:09)</a>:</h4>
<p><a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/148" target="_blank" title="https://github.com/rust-lang/unsafe-code-guidelines/issues/148">https://github.com/rust-lang/unsafe-code-guidelines/issues/148</a></p>



<a name="184982911"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184982911" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184982911">(Jan 07 2020 at 05:10)</a>:</h4>
<p>but I think that's not a problem in this case because the reference doesn't point directly within the owning struct</p>



<a name="184983002"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting%20Locks%20on%20Std%20IO/near/184983002" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Transmuting.20Locks.20on.20Std.20IO.html#184983002">(Jan 07 2020 at 05:12)</a>:</h4>
<p>there's also <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/125" target="_blank" title="https://github.com/rust-lang/unsafe-code-guidelines/issues/125">https://github.com/rust-lang/unsafe-code-guidelines/issues/125</a>, but that shouldn't be an issue as long as you don't drop the lock before dropping the struct as a whole</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>